DeriveGamemode( "base" );

V = { };
local meta = FindMetaTable( "Player" );
local emeta = FindMetaTable( "Entity" );

GM.Name = "Vein";
GM.Author = "Disseminate";
GM.Website = "http://facepunch.com/showthread.php?t=1148261";
GM.Email = "disseminate@luaforfood.com";

math.randomseed( os.time() );

game.AddParticles( "particles/vman_nuke.pcf" );
PrecacheParticleSystem( "dustwave_tracer" );

V.MaleValidModels = { };
V.MaleValidModels[1] = {
	Model = "models/humans/modern/male_01_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[2] = {
	Model = "models/humans/modern/male_01_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[3] = {
	Model = "models/humans/modern/male_01_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[4] = {
	Model = "models/humans/modern/male_02_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[5] = {
	Model = "models/humans/modern/male_02_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[6] = {
	Model = "models/humans/modern/male_02_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[7] = {
	Model = "models/humans/modern/male_03_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[8] = {
	Model = "models/humans/modern/male_03_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[9] = {
	Model = "models/humans/modern/male_03_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[10] = {
	Model = "models/humans/modern/male_03_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[11] = {
	Model = "models/humans/modern/male_03_05.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[12] = {
	Model = "models/humans/modern/male_03_06.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[13] = {
	Model = "models/humans/modern/male_03_07.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[14] = {
	Model = "models/humans/modern/male_04_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[15] = {
	Model = "models/humans/modern/male_04_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[16] = {
	Model = "models/humans/modern/male_04_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[17] = {
	Model = "models/humans/modern/male_04_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[18] = {
	Model = "models/humans/modern/male_05_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[19] = {
	Model = "models/humans/modern/male_05_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[20] = {
	Model = "models/humans/modern/male_05_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[21] = {
	Model = "models/humans/modern/male_05_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[22] = {
	Model = "models/humans/modern/male_05_05.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[23] = {
	Model = "models/humans/modern/male_06_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[24] = {
	Model = "models/humans/modern/male_06_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[25] = {
	Model = "models/humans/modern/male_06_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[26] = {
	Model = "models/humans/modern/male_06_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[27] = {
	Model = "models/humans/modern/male_06_05.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[28] = {
	Model = "models/humans/modern/male_07_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[29] = {
	Model = "models/humans/modern/male_07_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[30] = {
	Model = "models/humans/modern/male_07_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[31] = {
	Model = "models/humans/modern/male_07_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[32] = {
	Model = "models/humans/modern/male_07_05.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[33] = {
	Model = "models/humans/modern/male_07_06.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[34] = {
	Model = "models/humans/modern/male_08_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[35] = {
	Model = "models/humans/modern/male_08_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[36] = {
	Model = "models/humans/modern/male_08_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[37] = {
	Model = "models/humans/modern/male_08_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[38] = {
	Model = "models/humans/modern/male_09_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[39] = {
	Model = "models/humans/modern/male_09_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[40] = {
	Model = "models/humans/modern/male_09_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}
V.MaleValidModels[41] = {
	Model = "models/humans/modern/male_09_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
	}
}

V.FemaleValidModels = { };
V.FemaleValidModels[1] = {
	Model = "models/humans/modern/female_01.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
	}
}
V.FemaleValidModels[2] = {
	Model = "models/humans/modern/female_01.mdl",
	Skin = {
		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
	}
}
V.FemaleValidModels[3] = {
	Model = "models/humans/modern/female_02.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
	}
}
V.FemaleValidModels[4] = {
	Model = "models/humans/modern/female_02.mdl",
	Skin = {
		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
	}
}
V.FemaleValidModels[5] = {
	Model = "models/humans/modern/female_03.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
	}
}
V.FemaleValidModels[6] = {
	Model = "models/humans/modern/female_03.mdl",
	Skin = {
		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
	}
}
V.FemaleValidModels[7] = {
	Model = "models/humans/modern/female_04.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
	}
}
V.FemaleValidModels[8] = {
	Model = "models/humans/modern/female_04.mdl",
	Skin = {
		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
	}
}
V.FemaleValidModels[9] = {
	Model = "models/humans/modern/female_06.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
	}
}
V.FemaleValidModels[10] = {
	Model = "models/humans/modern/female_06.mdl",
	Skin = {
		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
	}
}
V.FemaleValidModels[11] = {
	Model = "models/humans/modern/female_07.mdl",
	Skin = {
		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
	}
}
V.FemaleValidModels[12] = {
	Model = "models/humans/modern/female_07.mdl",
	Skin = {
		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
	}
}

for _, v in pairs( V.MaleValidModels ) do
	
	util.PrecacheModel( v.Model );
	
end

for _, v in pairs( V.FemaleValidModels ) do
	
	util.PrecacheModel( v.Model );
	
end

V.Music = {
	{ "preface", 35.6048 },
	{ "theme", 68.3102 },
	{ "tune1", 135 },
	{ "tune2", 78.08 },
	{ "tune3", 60.0816 },
	{ "tune4", 115 },
	{ "tune5", 96.0783 },
	{ "tune6", 116.6628 },
	{ "tune7", 61.4661 },
	{ "tune8", 33.0971 },
	{ "tune9", 79.27 },
	{ "tune10", 72 },
	{ "tune11", 58.17 },
	{ "tune12", 61.75 },
	{ "tune13", 85 },
	{ "tune14", 56 },
	{ "tune15", 76 },
	{ "tune16", 46 },
	{ "tune17", 15 },
	{ "tune18", 11.285 },
	{ "tune19", 130 },
	{ "youaredead", 68.5191 },
};

function meta:IsFemale()
	
	if( string.find( string.lower( self:GetModel() ), "female" ) ) then
		
		return true;
		
	end
	
	return false;
	
end

function V.ModelToInt( mdl, skin )
	
	for k, v in pairs( V.MaleValidModels ) do
		
		if( v.Model == mdl and table.HasValue( v.Skin, skin ) ) then
			
			return k;
			
		end
		
	end
	
	for k, v in pairs( V.FemaleValidModels ) do
		
		if( v.Model == mdl and table.HasValue( v.Skin, skin ) ) then
			
			return k;
			
		end
		
	end
	
end

function V.GoodChar( model, skin, gender, name, desc )
	
	if( gender != 0 and gender != 1 ) then
		
		return false, "Invalid gender!";
		
	end
	
	if( gender == 0 and !V.MaleValidModels[model] ) then
		
		return false, "Invalid model!";
		
	end
	
	if( gender == 1 and !V.FemaleValidModels[model] ) then
		
		return false, "Invalid model!";
		
	end
	
	if( gender == 0 and !V.MaleValidModels[model].Skin[skin] ) then
		
		return false, "Invalid skin!";
		
	end
	
	if( gender == 1 and !V.MaleValidModels[model].Skin[skin] ) then
		
		return false, "Invalid skin!";
		
	end
	
	if( string.len( name ) < 5 ) then
		
		return false, "Name is too short.";
		
	end
	
	if( string.len( name ) > 30 ) then
		
		return false, "Name is too long.";
		
	end
	
	if( string.len( desc ) > V.Config.MaxDescLen ) then
		
		return false, "Description is too long.";
		
	end
	
	return true;
	
end

function GM:GetGameDescription()
	
	return "Vein";
	
end

function V.FindPlayer( name )
	
	name = string.lower( name );
	
	for k, v in pairs( player.GetAll() ) do
		
		if( string.find( string.lower( v:RPName() ), name ) ) then
			return v;
		end
		
		if( string.find( string.lower( v:Nick() ), name ) ) then
			return v;
		end
		
		if( string.lower( v:SteamID() ) == name ) then
			return v;
		end
		
	end

end

function V.ValidateDirectories()
	
	if( !file.IsDir( "Vein", "DATA" ) ) then
		
		file.CreateDir( "Vein" );
		
	end
	
	if( !file.IsDir( "Vein/logs", "DATA" ) ) then
		
		file.CreateDir( "Vein/logs" );
		
	end
	
	if( !file.IsDir( "Vein/settings", "DATA" ) ) then
		
		file.CreateDir( "Vein/settings" );
		file.Write( "Vein/settings/settings.txt", "" );
		
	end
	
	if( !file.IsDir( "Vein/mapdata", "DATA" ) ) then
		
		file.CreateDir( "Vein/mapdata" );
		
	end
	
	if( !file.IsDir( "Vein/navmeshes", "DATA" ) ) then
		
		file.CreateDir( "Vein/navmeshes" );
		
	end
	
end

function meta:CanSee( ent )
	
	local trace = { };
	trace.start = self:EyePos();
	trace.endpos = ent:EyePos();
	trace.filter = { self, ent };
	trace.mask = MASK_VISIBLE;
	local tr = util.TraceLine( trace );
	
	if( tr.Fraction == 1.0 ) then
		
		return true;
		
	end
	
	return false;
	
end

function meta:CanHear( ent )
	
	local trace = { };
	trace.start = self:EyePos();
	trace.endpos = ent:EyePos();
	trace.filter = self;
	trace.mask = MASK_SOLID;
	local tr = util.TraceLine( trace );
	
	if( IsValid( tr.Entity ) and tr.Entity:EntIndex() == ent:EntIndex() ) then
		
		return true;
		
	end
	
	return false;
	
end

function meta:CanSeePos( pos )
	
	local trace = { };
	trace.start = self:EyePos();
	trace.endpos = pos;
	trace.filter = self;
	local tr = util.TraceLine( trace );
	
	if( tr.Fraction == 1.0 ) then
		
		return true;
		
	end
	
	return false;
	
end

function GM:GetPlayerSpeed( ply )
	
	local walk = 110;
	local run = 250;
	
	run = run + ( ( run - walk ) / 4 ) * V.STAT.GetStatus( ply, V.STAT.STATUS_EXHAUSTION );
	
	local invPerc = ( 250 - V.I.GetWeight( ply ) ) / 250;
	
	walk = walk * invPerc;
	run = run * invPerc;
	
	if( ply.LastShot and CurTime() - ply.LastShot < ply.LastShotDelay ) then
		
		walk = 1;
		run = 1;
		
	end
	
	return walk, run;
	
end

function GM:Move( ply, data )
	
	if( !ply or !ply:IsValid() ) then return end
	
	if( ply.Chair and ply.Chair:IsValid() ) then
		
		data:SetVelocity( Vector() );
		return true;
		
	end
	
end

function GM:SetupMove( ply, data )
	
	if( !ply or !ply:IsValid() ) then return end
	
	if( ply.Chair and ply.Chair:IsValid() ) then
		
		data:SetVelocity( Vector() );
		data:SetOrigin( ply.Chair:GetPos() );
		return true;
		
	end
	
end

V.CCMODE_CREATE_N = 0;
V.CCMODE_SELECT_N = 1;
V.CCMODE_DELETE = 2;
V.CCMODE_CREATE = 3;
V.CCMODE_SELECT = 4;

V.ZombieModels = {
	"models/nmr_zombie/berny.mdl",
	"models/nmr_zombie/casual_02.mdl",
	"models/nmr_zombie/herby.mdl",
	"models/nmr_zombie/jogger.mdl",
	"models/nmr_zombie/julie.mdl",
	"models/nmr_zombie/maxx.mdl",
	"models/nmr_zombie/officezom.mdl",
	"models/nmr_zombie/toby.mdl",
};

V.InstantCrushDeath = {
	"func_tracktrain",
};

function emeta:IsZombie()
	
	return ( self:GetClass() == "v_zombie" );
	
end

function GM:ShouldCollide( e1, e2 )
	
	if( e1 and e2 and e1:IsValid() and e2:IsValid() ) then
		
		if( e1:IsZombie() and e2:IsZombie() ) then return false end
		if( e1:IsPlayer() and e2:IsPlayer() ) then return false end
		
		if( e1:IsPlayer() and e2:IsNotSolid() ) then return false end
		if( e2:IsPlayer() and e1:IsNotSolid() ) then return false end
		
	end
	
	return true;
	
end

function V.SanitizeString( arg )
	
	local ret = string.lower( arg );
	ret = string.gsub( ret, "[^%a^%s]", "" );
	ret = string.gsub( ret, " his", "" );
	ret = string.gsub( ret, " her", "" );
	ret = string.gsub( ret, " their", "" );
	ret = string.gsub( ret, " its", "" );
	ret = string.gsub( ret, " the", "" );
	ret = string.gsub( ret, " to", "" );
	ret = string.gsub( ret, " a", "" );
	ret = string.gsub( ret, " him", "" );
	ret = string.Trim( ret );
	return ret;
	
end

function V.OnScreen( ply, ent )
	
	if( type( ent ) != "Entity" and type( ent ) != "NPC" ) then
		
		local d = ply:GetAimVector():Dot( ( ent - ply:GetPos() ):GetNormal() );
		
		if( d > 0.55 ) then
			
			return true;
			
		end
		
		return false;
		
	end
	
	local d = ply:GetAimVector():Dot( ( ent:GetPos() - ply:GetPos() ):GetNormal() );
	
	if( d > 0.55 ) then
		
		return true;
		
	end
	
	return false;
	
end

function V.GetAimMod( ply )
	
	return 1;
	
end

function V.Outside( pos )
	
	local trace = { };
	trace.start = pos;
	trace.endpos = trace.start + Vector( 0, 0, 32768 );
	trace.mask = MASK_BLOCKLOS;
	local tr = util.TraceLine( trace );
	
	if( tr.HitSky ) then return true end
	
	return false;
	
end

function GM:OnReloaded()
	
	if( SERVER ) then
		
		
		
	else
		
		--V.CC.KillVGUIComponents();
		
	end
	
end

V.MD = { };

function V.MD.InitPostEntity()
	
end